package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.ResourceDto;
import com.zzyl.entity.Resource;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.service.ResourceService;
import com.zzyl.utils.EmptyUtil;
import com.zzyl.utils.NoProcessing;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.ResourceVo;
import com.zzyl.vo.TreeItemVo;
import com.zzyl.vo.TreeVo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

@Service
@RequiredArgsConstructor
public class ResourceServiceImpl implements ResourceService {

    private final ResourceMapper resourceMapper;

    @Override
    public List<ResourceVo> getList(ResourceDto resourceDto) {
        List<Resource> resourceList = resourceMapper.getList(resourceDto);
        List<ResourceVo> resourceVoList = BeanUtil.copyToList(resourceList, ResourceVo.class);
        return resourceVoList;
    }

    @Override
    public TreeVo getTree(ResourceDto resourceDto) {
        //第一步，将所有的查询条件封装到一个对象当中
        //需要符合的条件有，需要的是根节点下的所有资源，本项目中的根节点总共占了6位
        //能够添加的菜单配置必须是和启动的
        //类型是菜单配置，菜单配置是"m"，按钮配置是"r"，m是menu菜单的缩写，n是右边按钮区域right的缩写
        ResourceDto resourceDto1 = resourceDto.builder()
                //这里一定要注意去0，否则只能获取到当前父节点的所有子节点
                .parentResourceNo(NoProcessing.processString(SuperConstant.ROOT_PARENT_ID))
                .dataState(SuperConstant.DATA_STATE_0)
                .resourceType(SuperConstant.MENU)
                .build();

        //第二步，调用mapper层的方法，获取所有符合条件的资源
        List<Resource> resourceList = resourceMapper.getList(resourceDto1);

        //第三步，定义TreeVo中的集合属性
        List<TreeItemVo> items = new ArrayList<>();

        //第四步,创建TreeNodeConfig对象，将name字段改为label与后端响应参数保持一致
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        treeNodeConfig.setNameKey("label");


        //第五步，调用huTool依赖的TreeUtil工具类
        List<Tree<String>> trees = TreeUtil.build(resourceList, SuperConstant.ROOT_PARENT_ID,treeNodeConfig, (resource, treeNode) -> {
            //resource是遍历resourceList出来的代表单个资源对象
            //treeNode代表的是huTool工具构建的树节点对象
            treeNode.setId(resource.getResourceNo()); //告诉huTool工具当前资源的id
            treeNode.setParentId(resource.getParentResourceNo()); //告诉huTool工具当前资源父节点的id
            treeNode.setName(resource.getResourceName()); //告诉huTool工具当前资源的名字
        });
        
        //第六步，将List<Tree<String>>类型对象转为List<TreeItemVo>类型对象
        List<TreeItemVo> children = BeanUtil.copyToList(trees, TreeItemVo.class);

        //第七步，伪造一个根节点对象，将根节点下的三级节点的集合封装到根节点中
        TreeItemVo treeItemVo = new TreeItemVo(SuperConstant.ROOT_PARENT_ID,"智慧养老院",children);

        //第八步，将上述根节点对象连带根节点对象下的children添加到items集合中
        items.add(treeItemVo);

        //第八步，将上述对象封装到TreeVo中返回
        return TreeVo.builder().items(items).build();
    }

    @Override
    public void insertResource(ResourceDto resourceDto) {
        //第一步，将ResourceDto对象转换为Resource对象
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);

        //第二步，根据resource中的parentResourceNo获取父资源，再将父资源的状态设置到resource对象中
        Resource resourceParent =  resourceMapper.selectByparentResourceNo(resource.getParentResourceNo());
        resource.setDataState(resourceParent.getDataState());

        //第三步，生成resource对象的resourceNo值
        String resourceNo = createResourceNo(resource);

        //第四步，将生成的resourceNo设置到resource对象中
        resource.setResourceNo(resourceNo);

        //第五步，调用mapper层添加方法
        resourceMapper.insertSelective(resource);
    }

    public String createResourceNo(Resource resource) {
        //如果是添加按钮，那么可以直接添加
        //第一步，判断是否是添加菜单，且层级不能够大于或者等于3，由于根节点自占了两级，所以层级不能大于等于5
        if (resource.getResourceType().equals(SuperConstant.MENU)
                && NoProcessing.processString(resource.getParentResourceNo()).length() / 3 >= 5){
            throw new BaseException(BasicEnum.RESOURCE_DEPTH_UPPER_LIMIT);
        }

        //第二步，判断父节点是否有子节点
        ResourceDto resourceDto = ResourceDto.builder().parentResourceNo(resource.getParentResourceNo()).build();
        List<Resource> list = resourceMapper.getList(resourceDto);

        //第三步，判断list集合是否为空
        if (EmptyUtil.isNullOrEmpty(list)){
            //为空的逻辑是在
            return NoProcessing.createNo(resource.getParentResourceNo(),false);
        }else {
            //不为空的逻辑是获取最大的子节点然后+1
            Long max = list.stream().map(resource1 ->
                Long.valueOf(resource1.getResourceNo())
            ).max(Comparator.comparing(Long::intValue)).get();
            return NoProcessing.createNo(String.valueOf(max),true);
        }
    }

    @Override
    public void update(ResourceDto resourceDto) {
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        resourceMapper.updateByPrimaryKeySelective(resource);
    }

    @Override
    public void updateState(ResourceDto resourceDto) {
        Resource resource1 = BeanUtil.toBean(resourceDto, Resource.class);
        //把前端传回来的状态取反值，为了获取与目标状态不同的子节点的集合
        if (resourceDto.getDataState().equals(SuperConstant.DATA_STATE_0)){
            resourceDto.setDataState(SuperConstant.DATA_STATE_1);
        }else {
            resourceDto.setDataState(SuperConstant.DATA_STATE_0);
        }
        //获取完整的父级No
        String parentResourceNoAll = resourceDto.getParentResourceNo();
        //取当前资源的父级下的所有资源，也包括同级资源
        resourceDto.setParentResourceNo(NoProcessing.processString(resourceDto.getParentResourceNo()));
        List<Resource> list = resourceMapper.getList(resourceDto);
        //判断该集合是否为空
        //不为空则改当前节点以及子节点的状态
        if (ObjectUtil.isNotEmpty(list)){
            resourceMapper.updateState(resource1);
            for (Resource resource : list) {
                //这一步是为了避免修改同级节点的状态，通过完整的父级No来判断遍历后的集合的元素是否为同级节点
                if (!(resource.getParentResourceNo().equals(parentResourceNoAll))){
                    resource.setDataState(resource1.getDataState());
                    resourceMapper.updateState(resource);
                }
            }
        //为空则直接改当前节点的状态
        }else {
            resourceMapper.updateState(resource1);
        }
    }

    @Override
    public List<Resource> deleteByResourceId(String menuId) {
        // Resource resource1 = BeanUtil.toBean(resourceDto, Resource.class);
        // //获取完整的父级No
        // String parentResourceNoAll = resourceDto.getParentResourceNo();
        //取当前资源的父级下的所有资源，也包括同级资源
        // resourceDto.setParentResourceNo(NoProcessing.processString(resourceDto.getParentResourceNo()));
        ResourceDto resourceDto = ResourceDto.builder().parentResourceNo(NoProcessing.processString(menuId)).build();
        List<Resource> list = resourceMapper.getList(resourceDto);
        //判断该集合是否为空
        //不为空则改当前节点以及子节点的状态
        if (ObjectUtil.isEmpty(list)){
            // for (Resource resource : list) {
            //     resourceMapper.deleteByResourceNo(resource.getResourceNo());
            //
            // }
            // resourceMapper.deleteByResourceNo(menuId);
            //为空则直接改当前节点的状态
            resourceMapper.deleteByResourceNo(menuId);
        }
        return list;
    }
}
